/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
#ifndef MCPY_BUILTINS_DICT_H
#define MCPY_BUILTINS_DICT_H

#include <algorithm>
#include <mc/dict.h>
#include <mc/exception.h>
#include <mc/variant.h>
#include <mcpy/exception.h>
#include <optional>
#include <tuple>
#include <vector>

#include "mcpy/builtins/dict_views.h"

namespace mcpy {

// ===== 获取方法 =====

/**
 * @brief 获取字典中键对应的值，如果不存在返回 None（泛型版本）
 * @tparam V 值类型
 */
template <typename V = mc::variant, typename Dict, typename Key>
auto dict_get(Dict& d, const Key& key) -> V {
    if (d.contains(key)) {
        if constexpr (std::is_same_v<V, mc::variant>) {
            return d[key];
        } else {
            return d[key].template as<V>();
        }
    }
    if constexpr (std::is_same_v<V, mc::variant>) {
        return mc::variant(); // None
    } else {
        return V{}; // 默认构造的值
    }
}

/**
 * @brief 获取字典中键对应的值，如果不存在返回默认值（泛型版本）
 * @tparam V 值类型
 */
template <typename V = mc::variant, typename Dict, typename Key, typename Default>
auto dict_get(Dict& d, const Key& key, const Default& default_value) -> V {
    if (d.contains(key)) {
        if constexpr (std::is_same_v<V, mc::variant>) {
            return d[key];
        } else {
            return d[key].template as<V>();
        }
    }
    if constexpr (std::is_same_v<V, mc::variant>) {
        return mc::variant(default_value);
    } else {
        return default_value;
    }
}

// ===== keys, values, items =====
// 注意：dict_keys, dict_values, dict_items 现在在 dict_views.h 中实现为视图对象

// ===== 修改方法 =====

/**
 * @brief 删除并返回指定键的值（泛型版本）
 * @tparam V 值类型
 * @throw mcpy::key_error 如果键不存在
 */
template <typename V = mc::variant, typename Dict, typename Key>
auto dict_pop(Dict& d, const Key& key) -> V {
    if (!d.contains(key)) {
        MC_THROW(mcpy::key_error, "键不存在: ${key}", ("key", key));
    }
    auto value = d[key];
    d.erase(key);
    if constexpr (std::is_same_v<V, mc::variant>) {
        return value;
    } else {
        return value.template as<V>();
    }
}

/**
 * @brief 删除并返回指定键的值，如果不存在返回默认值（泛型版本）
 * @tparam V 值类型
 */
template <typename V = mc::variant, typename Dict, typename Key, typename Default>
auto dict_pop(Dict& d, const Key& key, const Default& default_value) -> V {
    if (d.contains(key)) {
        auto value = d[key];
        d.erase(key);
        if constexpr (std::is_same_v<V, mc::variant>) {
            return value;
        } else {
            return value.template as<V>();
        }
    }
    if constexpr (std::is_same_v<V, mc::variant>) {
        return mc::variant(default_value);
    } else {
        return default_value;
    }
}

/**
 * @brief 删除并返回最后插入的键值对（泛型版本）
 * @tparam K 键类型
 * @tparam V 值类型
 * @throw mcpy::key_error 如果字典为空
 */
template <typename K = mc::variant, typename V = mc::variant>
auto dict_popitem(mc::dict& d) -> std::tuple<K, V> {
    if (d.empty()) {
        MC_THROW(mcpy::key_error, "popitem(): 字典为空");
    }

    // 获取最后一个元素
    auto it = d.begin();
    std::advance(it, d.size() - 1);
    auto key   = it->key;
    auto value = it->value;

    // 删除
    d.erase(key);

    if constexpr (std::is_same_v<K, mc::variant> && std::is_same_v<V, mc::variant>) {
        return std::make_tuple(key, value);
    } else if constexpr (std::is_same_v<K, mc::variant>) {
        return std::make_tuple(key, value.template as<V>());
    } else if constexpr (std::is_same_v<V, mc::variant>) {
        return std::make_tuple(key.template as<K>(), value);
    } else {
        return std::make_tuple(key.template as<K>(), value.template as<V>());
    }
}

/**
 * @brief 更新字典（合并另一个字典）
 */
inline void dict_update(mc::dict& d, const mc::dict& other) {
    for (const auto& entry : other) {
        d[entry.key] = entry.value;
    }
}

/**
 * @brief 如果键不存在，设置默认值并返回；如果存在，返回现有值
 */
template <typename Dict, typename Key>
auto dict_setdefault(Dict& d, const Key& key) -> mc::variant& {
    if (!d.contains(key)) {
        d[key] = mc::variant(); // None
    }
    return d[key];
}

/**
 * @brief 如果键不存在，设置默认值并返回；如果存在，返回现有值
 */
template <typename Dict, typename Key, typename Default>
auto dict_setdefault(Dict& d, const Key& key, const Default& default_value) -> mc::variant& {
    if (!d.contains(key)) {
        d[key] = mc::variant(default_value);
    }
    return d[key];
}

/**
 * @brief 删除指定键的键值对
 * @throw mcpy::key_error 如果键不存在
 */
template <typename Dict, typename Key>
void dict_delitem(Dict& d, const Key& key) {
    if (!d.erase(key)) {
        MC_THROW(mcpy::key_error, "键不存在: ${key}", ("key", key));
    }
}

// ===== 运算符支持 =====

/**
 * @brief 合并两个字典（Python 3.9+ | 运算符）
 */
inline auto dict_merge(const mc::dict& d1, const mc::dict& d2)
    -> mc::dict {
    mc::dict result;
    for (const auto& entry : d1) {
        result[entry.key] = entry.value;
    }
    for (const auto& entry : d2) {
        result[entry.key] = entry.value;
    }
    return result;
}

/**
 * @brief 就地合并字典（Python 3.9+ |= 运算符）
 */
inline auto dict_ior(mc::dict& d1, const mc::dict& d2)
    -> mc::dict& {
    for (const auto& entry : d2) {
        d1[entry.key] = entry.value;
    }
    return d1;
}

// ===== 字符串表示 =====

/**
 * @brief 生成字典的字符串表示
 */
inline std::string dict_repr(const mc::dict& d) {
    if (d.empty()) {
        return "{}";
    }

    std::string result = "{";
    bool        first  = true;

    for (const auto& entry : d) {
        if (!first) {
            result += ", ";
        }
        first = false;

        // 键的表示
        result += mc::to_string(entry.key);
        result += ": ";
        // 值的表示
        result += mc::to_string(entry.value);
    }

    result += "}";
    return result;
}

// ===== 构造函数支持 =====

/**
 * @brief 从键值对列表构造字典
 */
template <typename Container>
auto dict_construct(const Container& items) -> mc::dict {
    mc::dict result;

    for (const auto& item : items) {
        // item 是 tuple[K, V]
        result[std::get<0>(item)] = std::get<1>(item);
    }

    return result;
}

// ===== 字典推导式支持 =====

/**
 * @brief 字典推导式辅助函数（基础版本）
 *
 * 用法: auto d = dict_comprehension(source, [](auto& item) {
 *           return std::make_pair(key_expr, value_expr);
 *       });
 */
template <typename Container, typename Func>
auto dict_comprehension(const Container& container, Func&& func) -> mc::dict {
    mc::dict result;

    for (const auto& item : container) {
        auto kv          = func(item);
        result[kv.first] = kv.second;
    }

    return result;
}

/**
 * @brief 带条件的字典推导式
 *
 * 用法: auto d = dict_comprehension_if(source,
 *           [](auto& item) { return std::make_pair(k, v); },
 *           [](auto& item) { return condition; });
 */
template <typename Container, typename Func, typename Pred>
auto dict_comprehension_if(const Container& container, Func&& func, Pred&& pred)
    -> mc::dict {
    mc::dict result;

    for (const auto& item : container) {
        if (pred(item)) {
            auto kv          = func(item);
            result[kv.first] = kv.second;
        }
    }

    return result;
}

/**
 * @brief 嵌套字典推导式（两层循环）
 */
template <typename Container1, typename Container2, typename Func>
auto dict_comp_nested(const Container1& c1, const Container2& c2, Func&& func)
    -> mc::dict {
    mc::dict result;

    for (const auto& item1 : c1) {
        for (const auto& item2 : c2) {
            auto kv          = func(item1, item2);
            result[kv.first] = kv.second;
        }
    }

    return result;
}

/**
 * @brief 嵌套字典推导式（带条件）
 */
template <typename Container1, typename Container2, typename Func, typename Pred>
auto dict_comp_nested_if(const Container1& c1, const Container2& c2,
                         Func&& func, Pred&& pred) -> mc::dict {
    mc::dict result;

    for (const auto& item1 : c1) {
        for (const auto& item2 : c2) {
            if (pred(item1, item2)) {
                auto kv          = func(item1, item2);
                result[kv.first] = kv.second;
            }
        }
    }

    return result;
}

/**
 * @brief 从键序列创建字典（所有键对应同一个值）
 *
 * 类似 Python 的 dict.fromkeys(keys, value)
 *
 * @tparam Container 键容器类型
 * @tparam Value 值类型
 * @param keys 键的序列
 * @param value 所有键对应的值（默认为 None）
 * @return 新创建的字典
 */
template <typename Container, typename Value = mc::variant>
auto dict_fromkeys(const Container& keys, const Value& value = Value{}) -> mc::dict {
    mc::dict result;
    for (const auto& key : keys) {
        result[key] = value;
    }
    return result;
}

// ============================================================================
// 反向迭代
// ============================================================================

namespace detail {
/**
 * @brief 字典反向键迭代器视图
 *
 * 提供 Python reversed(dict) 的功能
 * 通过模板参数 Holder 控制存储方式：
 * - 引用类型 → 零拷贝
 * - 值类型 → 拥有数据
 */
template <typename K, typename Holder>
class dict_reversed_keys_view {
public:
    using dict_type     = mc::dict;
    using base_iterator = typename dict_type::const_reverse_iterator;

    // 自定义迭代器，提取 entry 中的 key
    class iterator {
    public:
        using iterator_category = std::bidirectional_iterator_tag;
        using value_type        = K;
        using difference_type   = std::ptrdiff_t;
        using pointer           = const K*;
        using reference         = K;

        explicit iterator(base_iterator it) : m_it(it) {
        }

        reference operator*() const {
            if constexpr (std::is_same_v<K, mc::variant>) {
                return m_it->key;
            } else {
                return m_it->key.template as<K>();
            }
        }

        iterator& operator++() {
            ++m_it;
            return *this;
        }

        iterator operator++(int) {
            iterator tmp = *this;
            ++(*this);
            return tmp;
        }

        bool operator==(const iterator& other) const {
            return m_it == other.m_it;
        }
        bool operator!=(const iterator& other) const {
            return m_it != other.m_it;
        }

    private:
        base_iterator m_it;
    };

    explicit dict_reversed_keys_view(Holder dict) : m_holder(std::forward<Holder>(dict)) {
    }

    iterator begin() const {
        return iterator(get_dict().rbegin());
    }
    iterator end() const {
        return iterator(get_dict().rend());
    }

    std::size_t size() const {
        return get_dict().size();
    }

private:
    Holder m_holder;

    const dict_type& get_dict() const {
        if constexpr (std::is_reference_v<Holder>) {
            return m_holder;
        } else {
            return m_holder;
        }
    }
};

} // namespace detail

/**
 * @brief 创建字典反向键视图的辅助函数（左值引用版本 - 零拷贝）
 */
template <typename K = mc::variant, typename Dict>
inline auto dict_reversed(const Dict& d) {
    return detail::dict_reversed_keys_view<K, const Dict&>(d);
}

/**
 * @brief 创建字典反向键视图的辅助函数（右值拷贝版本 - 拥有数据）
 */
template <typename K = mc::variant>
inline auto dict_reversed(mc::dict&& d) {
    return detail::dict_reversed_keys_view<K, mc::dict>(std::move(d));
}

} // namespace mcpy

#endif // MCPY_BUILTINS_DICT_H
